package com.querie.beans;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * This class implements the LSH approach and saves LSH buckets in the database.
 * The new user's bucket is calculated and he is saved along with the users falling in
 * his bucket.
 * 
 * @author smittal
 *
 */
public class LSH {

	public static void clusterSetsByLSH(Set<Integer> sessionIds, int numHashFunctions) throws Exception
	{
      DatabaseAccess databaseAccess = DatabaseAccess.getInstance();
      
	  String bucketName="";
      for(Integer sessionId : sessionIds)

      {
    	List<Long> minHashValues = databaseAccess.getMinHashValues(sessionId);
        for(int j=0;j<numHashFunctions;j++)
       {
           if((j+1)%5!=0)
           { //every 5 hashvalue is concatenated to become a bucketName
               bucketName = bucketName + minHashValues.get(j);
           }
           else
           {
        	   bucketName= bucketName + minHashValues.get(j);
                      
               databaseAccess.saveLSHBucket(bucketName, sessionId);

               bucketName = "";
           }
        }
      }
   }

	/**
	 * This function is used to compute similarity using LSH bucket approach. It can be used if we
	 * want to further improve calculation time. However, this may lead to a bit lower accuracy since
	 * similar users are approximated.
	 * 
	 * @param minHashOfQuery
	 * @return
	 * @throws Exception
	 */
   public static Set<Integer> similarityUsingLSH(List<Long> minHashOfQuery) throws Exception
   {
       int i=0;
       String bucketName="";
       DatabaseAccess readSessions = DatabaseAccess.getInstance();

       // s is All potential set indices.
       Set<Integer> s= new HashSet<Integer>();
       if(minHashOfQuery != null && minHashOfQuery.size() > 0)
       {
	       while(i < minHashOfQuery.size() && minHashOfQuery.get(i)!=null)
	       {
	           if((i+1)%5 !=0)
	           {
	               bucketName += minHashOfQuery.get(i);
	           }
	           else
	           {
	        	   bucketName= bucketName + minHashOfQuery.get(i);
	        	   
	        	   List<Integer> newList =  readSessions.getSetIdsInBucket(bucketName);
	        	   
	        	   if (newList != null) {
		        	   Iterator<Integer> it = newList.iterator();
		               while(it.hasNext())
		                   s.add((Integer)it.next());
	        	   }
	        	   
	               bucketName= "";
	           }
	           
	           i++;
	       }
       }
       return s;
   }
	
}